package com.sjsu.aws.doublebarrier;

import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.services.dynamodb.model.ComparisonOperator;
import com.amazonaws.services.dynamodb.model.Condition;
import com.amazonaws.services.dynamodb.model.ScanResult;
import com.sjsu.aws.db.QueryCriteria;
import com.sjsu.aws.db.TableOperationImpl;
import com.sjsu.aws.db.TableRow;
import com.sjsu.aws.ephermeralnode.EphemeralServiceImpl;

/**
 * 
 * @author Deepali Pawar
 * 
 */
public class DoubleBarrierServiceImpl implements DoubleBarrierService {
	private final static Logger	LOG	= Logger.getLogger(DoubleBarrierServiceImpl.class);
	
	private TableOperationImpl	        tableOperationImpl;
	private EphemeralServiceImpl	    ephemeralServiceImpl;
	private TableRow	                tableRow;
	private QueryCriteria	            criteria;
	
	public DoubleBarrierServiceImpl() throws Exception {
		this.tableOperationImpl = new TableOperationImpl();
		this.ephemeralServiceImpl = new EphemeralServiceImpl();
		this.tableRow = new TableRow();
		this.criteria = new QueryCriteria();
	}
	
	@Override
	public void deleteEphemeralNodesOnDisconnect() throws Exception {
		LOG.info("DoubleBarrier: Deleting Ephemeral Nodes On Disconnect");
		ephemeralServiceImpl.deleteEphemeralNodesOnDisconnect(
		        DoubleBarrierConstants.DBTABLENAME,
		        DoubleBarrierConstants.COLUMN_UUID_ID,
		        DoubleBarrierConstants.COLUMN_PARTICIPANT_ID);
	}
	
	@Override
	public void renewEphemeralMembership(DoubleBarrier db) throws Exception {
		LOG.info("DoubleBarrier: Renew Ephemeral Membership");
		ephemeralServiceImpl.renewEphemeralMembership(
		        DoubleBarrierConstants.DBTABLENAME,
		        DoubleBarrierConstants.COLUMN_UUID_ID,
		        DoubleBarrierConstants.COLUMN_END_TIMESTAMP,
		        DoubleBarrierConstants.COLUMN_PARTICIPANT_ID,
		        db.getParticipantId(), db.getEndTimestamp());
	}
	
	@Override
	public void deleteTimeOutSessionsForEphemeralNode() throws Exception {
		LOG.info("DoubleBarrier: Delete TimeOut Sessions For EphemeralNode");
		ephemeralServiceImpl.deleteTimeOutSessionsForEphemeralNode(
		        DoubleBarrierConstants.DBTABLENAME,
		        DoubleBarrierConstants.COLUMN_UUID_ID,
		        DoubleBarrierConstants.COLUMN_END_TIMESTAMP);
	}
	
	@Override
	public int getNoOfBarrierPaticipants(DoubleBarrier db) throws Exception {
		LOG.info("DoubleBarrier: Get No Of Barrier Paticipants");
		HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
		Condition condition = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(db.getBarrierId()));
		
		scanFilter.put(DoubleBarrierConstants.COLUMN_BARRIER_ID, condition);
		
		criteria.setScanFilter(scanFilter);
		ScanResult scanResult = tableOperationImpl.queryTable(
		        DoubleBarrierConstants.DBTABLENAME, criteria);
		LOG.info("No of Participants" + scanResult.getCount());
		return scanResult.getCount();
	}
	
	@Override
	public void addParticipantToBarrier(DoubleBarrier db) throws Exception {
		LOG.info("DoubleBarrier: Add Participant To Barrier");
		tableRow.setItem(createDoubleBarrierItem(db));
		tableOperationImpl.insertItem(DoubleBarrierConstants.DBTABLENAME,
		        tableRow);
	}
	
	@Override
	public void removeParticipantFromBarrier(DoubleBarrier db) throws Exception {
		LOG.info("DoubleBarrier: Remove Participant From Barrier");
		HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
		
		Condition condition1 = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(db.getBarrierId()));
		
		scanFilter.put(DoubleBarrierConstants.COLUMN_BARRIER_ID, condition1);
		
		Condition condition = new Condition().withComparisonOperator(
		        ComparisonOperator.EQ.toString()).withAttributeValueList(
		        new AttributeValue().withS(db.getParticipantId()));
		
		scanFilter.put(DoubleBarrierConstants.COLUMN_PARTICIPANT_ID, condition);
		criteria.setScanFilter(scanFilter);
		
		String uuid = null;
		ScanResult scanResult = tableOperationImpl.queryTable(
		        DoubleBarrierConstants.DBTABLENAME, criteria);
		LOG.info("Read Config" + scanResult.getCount());
		
		for (int i = 0; i < scanResult.getCount(); i++) {
			HashMap<String, AttributeValue> item = (HashMap<String, AttributeValue>) scanResult
			        .getItems().get(i);
			if (item.get(DoubleBarrierConstants.COLUMN_UUID_ID).getS() != null) {
				uuid = item.get(DoubleBarrierConstants.COLUMN_UUID_ID).getS();
				LOG.info("UUID value is " + uuid);
				tableRow.setDeleteKey(uuid);
				tableOperationImpl.deleteItem(
				        DoubleBarrierConstants.DBTABLENAME, tableRow);
			}
		}
	}
	/**
	 * 
	 * @param db
	 * @return
	 * @throws Exception
	 */
	private Map<String, AttributeValue> createDoubleBarrierItem(DoubleBarrier db)
	        throws Exception {
		LOG.info("DoubleBarrier: Create Double Barrier Item");
		Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
		item.put(DoubleBarrierConstants.COLUMN_UUID_ID,
		        new AttributeValue(db.getUuid()));
		item.put(DoubleBarrierConstants.COLUMN_BARRIER_ID, new AttributeValue(
		        db.getBarrierId()));
		item.put(DoubleBarrierConstants.COLUMN_PARTICIPANT_ID,
		        new AttributeValue(db.getParticipantId()));
		item.put(DoubleBarrierConstants.COLUMN_JOB_ID,
		        new AttributeValue(db.getJobId()));
		item.put(
		        DoubleBarrierConstants.COLUMN_END_TIMESTAMP,
		        new AttributeValue().withN(String.valueOf(db.getEndTimestamp())));
		return item;
	}
}
